﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UnitTestUtils.DB
{
    /// <summary>
    /// Models the interface exposed by LinqToSql Table.
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public interface ITable<TEntity> : IQueryable<TEntity>, IQueryProvider, IEnumerable<TEntity>
        //, ITable, IQueryable, IEnumerable, IListSource
        where TEntity : class
    {
        /// <summary>
        /// Gets the System.Data.Linq.DataContext that has been used to retrieve this System.Data.Linq.Table&lt;TEntity&gt;.
        /// </summary>
        System.Data.Linq.DataContext Context { get; }
        
        /// <summary>
        /// Gets a value that indicates the value of System.Data.Linq.DataContext.ObjectTrackingEnabled 
        /// in the System.Data.Linq.DataContext that has been used to retrieved this System.Data.Linq.Table&lt;TEntity&gt;.
        /// </summary>
        bool IsReadOnly { get; }

        /// <summary>
        /// Attaches a disconnected or "detached" entity to a new System.Data.Linq.DataContext 
        /// when original values are required for optimistic concurrency checks.
        /// </summary>
        /// <param name="entity">The entity to be attached.</param>
        void Attach(TEntity entity);
        
        /// <summary>
        /// Attaches an entity to the System.Data.Linq.DataContext in either a modified or unmodified state.
        /// </summary>
        /// <param name="entity">The entity to be attached.</param>
        /// <param name="asModified">true if the object has a timestamp or RowVersion member, false if original 
        /// values are being used for the optimistic concurrency check.</param>
        void Attach(TEntity entity, bool asModified);
           
        /// <summary>
        /// Attaches an entity to the System.Data.Linq.DataContext in either a modified 
        /// or unmodified state by specifying both the entity and its original state.
        /// </summary>
        /// <param name="entity">The entity to be attached.</param>
        /// <param name="original">An instance of the same entity type with data members that contain the original
        /// values.</param>
        void Attach(TEntity entity, TEntity original);
        
        /// <summary>
        /// Attaches all entities of a collection to the System.Data.Linq.DataContext
        /// in either a modified or unmodified state.
        /// </summary>
        /// <typeparam name="TSubEntity">The type of entities to attach.</typeparam>
        /// <param name="entities">The collection of entities.</param>
        void AttachAll<TSubEntity>(IEnumerable<TSubEntity> entities) where TSubEntity : TEntity;
        
        /// <summary>
        /// Attaches all entities of a collection to the System.Data.Linq.DataContext 
        /// in either a modified or unmodified state.
        /// </summary>
        /// <typeparam name="TSubEntity">The type of entities to attach.</typeparam>
        /// <param name="entities">The collection of entities.</param>
        /// <param name="asModified">true if the object has a timestamp or RowVersion member, false if original 
        /// values are being used for the optimistic concurrency check.</param>
        void AttachAll<TSubEntity>(IEnumerable<TSubEntity> entities, bool asModified) where TSubEntity : TEntity;
        
        /// <summary>
        /// Puts all entities from the collection into a pending delete state.
        /// </summary>
        /// <typeparam name="TSubEntity">The type of the elements to delete.</typeparam>
        /// <param name="entities"> The entities being removed.</param>
        void DeleteAllOnSubmit<TSubEntity>(IEnumerable<TSubEntity> entities) where TSubEntity : TEntity;
        
        /// <summary>
        /// Puts an entity from this table into a pending delete state.
        /// </summary>
        /// <param name="entity">The entity to be deleted.</param>
        void DeleteOnSubmit(TEntity entity);
        
        /// <summary>
        /// Gets an enumerator for the collection.
        /// </summary>
        /// <returns>An enumerator that can be used to iterate through the collection.</returns>
        new IEnumerator<TEntity> GetEnumerator();
        
        /// <summary>
        /// Returns an array of modified members that contain their current and original values.
        /// </summary>
        /// <param name="entity">The entity from which to get the array.</param>
        /// <returns>An array of modified members.</returns>
        System.Data.Linq.ModifiedMemberInfo[] GetModifiedMembers(TEntity entity);
        
        /// <summary>
        /// Creates a new list for binding to a data source.
        /// </summary>
        /// <returns>A new System.ComponentModel.IBindingList for binding to a data source.</returns>
        System.ComponentModel.IBindingList GetNewBindingList();
        
        /// <summary>
        /// Returns an instance that contains the original state of the entity.
        /// </summary>
        /// <param name="entity">The entity whose original state is to be returned.</param>
        /// <returns>A System.Data.Linq.Table&lt;TEntity&gt; instance in its original state.</returns>
        TEntity GetOriginalEntityState(TEntity entity);
        
        /// <summary>
        /// Adds all entities of a collection to the System.Data.Linq.DataContext in a pending insert state.
        /// </summary>
        /// <typeparam name="TSubEntity">The type of the elements to insert.</typeparam>
        /// <param name="entities">The entities to add.</param>
        void InsertAllOnSubmit<TSubEntity>(IEnumerable<TSubEntity> entities) where TSubEntity : TEntity;
        
        /// <summary>
        /// Adds an entity in a pending insert state to this System.Data.Linq.Table&lt;TEntity&gt;.
        /// </summary>
        /// <param name="entity">The entity to be added.</param>
        void InsertOnSubmit(TEntity entity);
        
        /// <summary>
        /// Returns a string that represents the table.
        /// </summary>
        /// <returns>A string representing the table.</returns>
        string ToString();
    }
}